# video_processing/ffmpeg_cutter.py - Video cutting using FFmpeg

import os
import subprocess
import logging
import tempfile

logger = logging.getLogger(__name__)


class FFmpegCutter:
    """
    Class for cutting video segments using FFmpeg
    """

    def __init__(self, ffmpeg_path="ffmpeg"):
        self.ffmpeg_path = ffmpeg_path

        # Verify FFmpeg is installed
        try:
            subprocess.run([self.ffmpeg_path, "-version"],
                           stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE,
                           check=True)
            logger.info("FFmpeg found and working")
        except (subprocess.SubprocessError, FileNotFoundError):
            logger.warning("FFmpeg not found or not working properly, using 'ffmpeg' command")
            self.ffmpeg_path = "ffmpeg"

    def cut_segment(self, input_file, output_file, start_time, end_time):
        """
        Cut a segment from the input video

        Args:
            input_file: Path to the input video file
            output_file: Path to save the output video
            start_time: Start time in seconds
            end_time: End time in seconds

        Returns:
            True if successful, False otherwise
        """
        if not os.path.exists(input_file):
            logger.error(f"Input file not found: {input_file}")
            return False

        # Create the output directory if it doesn't exist
        os.makedirs(os.path.dirname(output_file), exist_ok=True)

        # Calculate duration
        duration = end_time - start_time

        if duration <= 0:
            logger.error(f"Invalid duration: {duration}")
            return False

        try:
            # Build FFmpeg command
            command = [
                self.ffmpeg_path,
                "-y",  # Overwrite output file if it exists
                "-ss", str(start_time),  # Start time
                "-i", input_file,  # Input file
                "-t", str(duration),  # Duration
                "-c", "copy",  # Copy codecs (fast)
                "-avoid_negative_ts", "1",  # Avoid negative timestamps
                output_file  # Output file
            ]

            # Execute the command
            logger.info(f"Executing FFmpeg command: {' '.join(command)}")

            process = subprocess.run(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                check=True
            )

            # Check if output file was created
            if os.path.exists(output_file) and os.path.getsize(output_file) > 0:
                logger.info(f"Successfully cut segment to {output_file}")
                return True
            else:
                logger.error("FFmpeg did not create a valid output file")
                return False

        except subprocess.CalledProcessError as e:
            logger.error(f"FFmpeg error: {e}")
            logger.error(f"FFmpeg stderr: {e.stderr.decode('utf-8', errors='ignore')}")
            return False
        except Exception as e:
            logger.error(f"Error cutting video segment: {str(e)}")
            return False

    def cut_segment_accurate(self, input_file, output_file, start_time, end_time):
        """
        Cut a segment from the input video with more accurate timing
        (re-encodes the video for more precise timing)

        Args:
            input_file: Path to the input video file
            output_file: Path to save the output video
            start_time: Start time in seconds
            end_time: End time in seconds

        Returns:
            True if successful, False otherwise
        """
        if not os.path.exists(input_file):
            logger.error(f"Input file not found: {input_file}")
            return False

        # Create the output directory if it doesn't exist
        os.makedirs(os.path.dirname(output_file), exist_ok=True)

        # Calculate duration
        duration = end_time - start_time

        if duration <= 0:
            logger.error(f"Invalid duration: {duration}")
            return False

        try:
            # Build FFmpeg command
            command = [
                self.ffmpeg_path,
                "-y",  # Overwrite output file if it exists
                "-ss", str(start_time),  # Start time
                "-i", input_file,  # Input file
                "-t", str(duration),  # Duration
                "-c:v", "libx264",  # Video codec
                "-c:a", "aac",  # Audio codec
                "-strict", "experimental",  # Allow experimental codecs
                "-b:a", "128k",  # Audio bitrate
                "-movflags", "+faststart",  # Optimize for web streaming
                output_file  # Output file
            ]

            # Execute the command
            logger.info(f"Executing FFmpeg command: {' '.join(command)}")

            process = subprocess.run(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                check=True
            )

            # Check if output file was created
            if os.path.exists(output_file) and os.path.getsize(output_file) > 0:
                logger.info(f"Successfully cut segment to {output_file}")
                return True
            else:
                logger.error("FFmpeg did not create a valid output file")
                return False

        except subprocess.CalledProcessError as e:
            logger.error(f"FFmpeg error: {e}")
            logger.error(f"FFmpeg stderr: {e.stderr.decode('utf-8', errors='ignore')}")
            return False
        except Exception as e:
            logger.error(f"Error cutting video segment: {str(e)}")
            return False

    def generate_thumbnail(self, video_path, output_path, time_position=None):
        """
        Generate a thumbnail from a video

        Args:
            video_path: Path to the input video file
            output_path: Path to save the thumbnail image
            time_position: Time position in seconds (if None, uses the middle of the video)

        Returns:
            True if successful, False otherwise
        """
        if not os.path.exists(video_path):
            logger.error(f"Input file not found: {video_path}")
            return False

        # Create the output directory if it doesn't exist
        os.makedirs(os.path.dirname(output_path), exist_ok=True)

        try:
            # If time_position is not specified, determine the middle of the video
            if time_position is None:
                # Get video duration using FFprobe
                duration_cmd = [
                    "ffprobe",
                    "-v", "error",
                    "-show_entries", "format=duration",
                    "-of", "default=noprint_wrappers=1:nokey=1",
                    video_path
                ]

                duration_result = subprocess.run(
                    duration_cmd,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True
                )

                try:
                    duration = float(duration_result.stdout.strip())
                    time_position = duration / 2
                except (ValueError, TypeError):
                    logger.warning("Could not determine video duration, using 0 seconds")
                    time_position = 0

            # Build FFmpeg command
            command = [
                self.ffmpeg_path,
                "-y",  # Overwrite output file if it exists
                "-ss", str(time_position),  # Seek position
                "-i", video_path,  # Input file
                "-vframes", "1",  # Extract 1 frame
                "-q:v", "2",  # Quality level (lower is better)
                output_path  # Output file
            ]

            # Execute the command
            logger.info(f"Executing FFmpeg command: {' '.join(command)}")

            process = subprocess.run(
                command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                check=True
            )

            # Check if output file was created
            if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
                logger.info(f"Successfully generated thumbnail at {output_path}")
                return True
            else:
                logger.error("FFmpeg did not create a valid thumbnail")
                return False

        except subprocess.CalledProcessError as e:
            logger.error(f"FFmpeg error: {e}")
            logger.error(f"FFmpeg stderr: {e.stderr.decode('utf-8', errors='ignore')}")
            return False
        except Exception as e:
            logger.error(f"Error generating thumbnail: {str(e)}")
            return False